package edu.kit.csl.cratylus.extraction;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;

import edu.kit.csl.cratylus.datatypes.BadParameterValueException;
import edu.kit.csl.cratylus.datatypes.Word;
import edu.kit.csl.cratylus.io.Logger;
import edu.kit.csl.cratylus.ui.Configuration;

/**
 * This writing system should be used in most of the cases. The phonemes are
 * translated one by one into a one character representation. This mapping is
 * taken from a mapping file referenced by the parameter p2gFile.
 */
public class MappingWritingSystem implements WritingSystem {
	
	private HashMap<String, String> mapping;
	
	/**
	 * Sole constructor. Fetches the p2gFile parameter and loads the mapping
	 * from the file.
	 * 
	 * @throws BadParameterValueException if p2gFile does not reference a valid
	 * 			mapping file
	 */
	public MappingWritingSystem() throws BadParameterValueException {
		mapping = new HashMap<String, String>();
		try {
			loadMapping(Configuration.getSingleton()
					.getString("p2gFile"));
		} catch (IOException e) {
			throw new BadParameterValueException("Error while loading the "
				+ "p2g mapping file: " + e.getMessage() + ". Please check "
				+ "the parameter p2gFile or use the writing system "
				+ "'dropBlanks'.");
		}
	}
	
	/**
	 * Loads the mapping from a file. The file should contain blank separated
	 * mapping pairs in each line. Commented lines start with a '#'.
	 * 
	 * @param fileName path to the file
	 * @throws IOException if the file is not readable or existing
	 */
	public void loadMapping(String fileName) throws IOException {
		FileInputStream fstream;
		fstream = new FileInputStream(fileName);
		DataInputStream in = new DataInputStream(fstream);
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String line;
		mapping.clear();
		// Read File Line By Line
		while ((line = br.readLine()) != null) {
			line = line.trim();
			if (line.startsWith("#") || line.isEmpty()) {
				continue;
			}
			String[] segments = line.split(" ");
			if (segments.length != 2) {
				Logger.getSingleton().error("Malformed line in p2g file "
					+ fileName + " skipped: " + line);
			} else {
				mapping.put(segments[0], segments[1]);
			}
		}
		br.close();
	}

	/**
	 * Converts the given blank separated phoneme string into its written
	 * representation. The internal mapping is applied one by one to the
	 * phonemes. If the string contains a new phoneme, find a new 
	 * representative character and update the mapping.
	 * 
	 * @param word the word containing a blank separated phoneme string
	 * @return a string without blanks where the phonemes are replaced
	 */
	@Override
	public String convert(Word word) {
		String[] phonemes = word.getContent().trim().split(" ");
		StringBuilder s = new StringBuilder();
		for (String phoneme : phonemes) {
			if (!mapping.containsKey(phoneme)) {
				Logger.getSingleton().error("P2G mapping failed. Unknown "
					+ "phoneme '" + phoneme + "'");
				continue;
			}
			s.append(mapping.get(phoneme));
		}
		return s.toString();
	}
}
